package delegate;

/*
* 动态代理的举例
* */

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Human{
    String getBelif();

    void eat(String food);
}

//被代理类
class SuperMan implements Human{

    @Override
    public String getBelif() {
        return "i believe i can fly";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}

/*
* 要想实现动态代理,要解决的问题
* 问题一:如何根据加载到内存中的代理类,动态的创建一个代理类及其对象
*
* 问题二:当通过代理类的对象调用方法时,如何动态的调用被代理类中的同名方法
*
*
* */

class ProxyFactory{
    //调用此方法,返回一个代理类的对象,解决问题一
    //obj:被代理的对象
    static public Object getProxyInstance(Object obj){
        MyInvocationhandler myInvocationhandler = new MyInvocationhandler();
        myInvocationhandler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),myInvocationhandler);
    }
}

class MyInvocationhandler implements InvocationHandler{

    private Object obj;//赋值时,也需要使用被代理对象进行赋值

    public void bind(Object obj){
        this.obj = obj;
    }
    //当我们通过代理类的对象,调用犯法a是,救护你自动的调用如下的方法:invoke()
    //将被代理类要执行的犯法a的功能就声明在invoke()方法中
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {

        //method:为代理类对象调用的犯法,此番发也就作为了被代理对象要调用的方法
        Object returnValue = method.invoke(obj, objects);

        //上述犯法的返回值就作为当前类中invoke()的返回值
        return returnValue;
    }
}

public class ProxyTest {

    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        String belif = proxyInstance.getBelif();
        System.out.println(belif);

        proxyInstance.eat("麻辣烫");
    }

}
